import PD from './index';
import type { ComponentPublicInstance } from "vue";
import type { APP_ROUTES } from "@/pd-libs/enum/app-routes";
import { WX_AUTH_DENY_ERROR, type WxUserPermission } from './wx-types';

export namespace UniHelp {
	/**
	 * 打开设置
	 */
	export function openSetting () : Promise<void> {
		return new Promise((r) => {
			uni.openSetting({
				complete : () => {
					r();
				}
			});
		});
	}
	/**
	 * toast 方法
	 * @params p - toast提示文案，或者完整的 UniApp.ShowToastOptions配置项
	 * @params duration - 仅在快速调用时生效，单位毫秒
	 */
	export function toast(title: string, duration?: number): Promise<void>
	export function toast(o: UniApp.ShowToastOptions): Promise<void>
	export function toast(p: string | UniApp.ShowToastOptions, duration?: number): Promise<void> {
		const DEFAULT_DURATION = 1500;
		//参数归一
		const _isFastCall = typeof p === 'string';
		const v: UniApp.ShowToastOptions = {
			title: _isFastCall ? p : p.title,
			icon: _isFastCall ? 'none' : p.icon,
			mask: _isFastCall ? true : p.mask,
			duration: _isFastCall ? (duration || DEFAULT_DURATION) : (p.duration || DEFAULT_DURATION),
		};
		return new Promise((r) => {
			uni.showToast({
				...v,
				complete() {
					setTimeout(r, v.duration);
				}
			});
		});
	}
	/**
	 * modal 方法
	 * @params p - modal提示内容，或者完整的 UniApp.ShowToastOptions配置项
	 * @params title 仅在快速调用时生效，标题文本
	 * @params showCancel 仅在快速调用时生效，是否显示取消按钮
	 */
	export function modal(content: string, title?: string, showCancel?: boolean): Promise<UniApp.ShowModalRes>
	export function modal(p: UniApp.ShowModalOptions): Promise<UniApp.ShowModalRes>
	export function modal(p: string | UniApp.ShowModalOptions, title = '提示', showCancel = false): Promise<UniApp.ShowModalRes> {
		//默认颜色
		const DEFAULT_CANCEL_COLOR = '#000000';
		const DEFAULT_CONFIRM_COLOR = '#05BE74';
		//参数归一
		const _isFastCall = typeof p === 'string';
		const v: UniApp.ShowModalOptions = {
			title: _isFastCall ? title : (p.title || '提示'),
			content: _isFastCall ? p : p.content,
			showCancel: _isFastCall ? Boolean(showCancel) : p.showCancel,
			cancelText: (p as UniApp.ShowModalOptions).cancelText || '取消',
			cancelColor: (p as UniApp.ShowModalOptions).cancelColor || DEFAULT_CANCEL_COLOR,
			confirmText: (p as UniApp.ShowModalOptions).confirmText || '确认',
			confirmColor: (p as UniApp.ShowModalOptions).confirmColor || DEFAULT_CONFIRM_COLOR,
			editable: _isFastCall ? false : (p.editable === undefined ? false : p.editable),
			placeholderText: _isFastCall ? '' : (p.placeholderText || '请输入'),
		};
		return new Promise((r, j) => {
			uni.showModal({
				...v,
				success: res => {
					res.confirm && r(res);
					res.cancel && j(res);
				},
				fail: err => {
					console.log(err);
				}
			});
		});
	}
	/**
	 * login 三方登录
	 * @return Promise(code)
	 */
	export function login(): Promise<string> {
		return new Promise((r, j) => {
			uni.login({
				success: res => {
					r(res.code);
				},
				fail: err => {
					j(err);
				}
			});
		});
	}
	/**
	 * getLocation -获取用户当前位置信息
	 * @params p - UniApp.GetLocationOptions，非必填
	 */
	export function getLocation(p?: UniApp.GetLocationOptions): Promise<UniApp.GetLocationSuccess> {
		return new Promise((r, j) => {
			uni.getLocation({
				...p,
				type: 'gcj02',
				success: res => {
					r(res);
				},
				fail: err => {
					j(err);
				}
			});
		});
	}
	/**
	 * openLocation -使用应用内置地图查看位置
	 * @params p - UniApp.GetLocationOptions，非必填
	 */

	export function openLocation(p : UniApp.OpenLocationOptions): Promise<void> {
		return new Promise((r, j) => {
			loading();
			uni.openLocation({
				...p,
				success() {
					r();
				},
				fail(err) {
					j(err);
				},
				complete() {
					loading(false);
				}
			});
		});
	}
	/**
	 * chooseLocation -选择位置
	 * @params p - UniApp.ChooseLocationOption
	 */
	export function chooseLocation(p?: UniApp.ChooseLocationOptions): Promise<UniApp.ChooseLocationSuccess> {
		return new Promise((r, j) => {
			uni.chooseLocation({
				...p,
				success: res => {
					r(res);
				},
				fail: err => {
					j(err);
				}
			});
		});
	}
	/**
	 * getStorage -获取缓存数据
	 * @params key - string
	 */
	export function getStorage<T>(key: string): T {
		return uni.getStorageSync(key);
	}
	/**
	 * setStorage -设置缓存数据
	 * @params key - string
	 * @params value - any
	 */
	export function setStorage(key: string, value: unknown) {
		uni.setStorageSync(key, value);
	}
	/**
	 * removeStorage -移除缓存数据
	 * @params key - string
	 */
	export function removeStorage(key: string) {
		uni.removeStorageSync(key);
	}
	/**
	 * loading -显示loading动画
	 * @param {boolean} flag 非必填，默认值为true，当传入false时，即调用hideLoding
	 * @param {string} title 非必填，showLoading时显示的文案信息
	 */
	export function loading(flag = true, title = '处理中...') {
		flag && uni.showLoading({
			mask: true,
			title
		});
		!flag && uni.hideLoading();
	}
	/**
	 * getSetting -获取小程序设置
	 * @params withSubscriptions - boolean，非必填，是否同时获取用户订阅状态
	 * @returns Promise(UniApp.GetSettingSuccessResult)
	 */
	export function getSetting(withSubscriptions = false): Promise<UniApp.GetSettingSuccessResult> {
		return new Promise((r, j) => {
			uni.getSetting({
				withSubscriptions,
				success: res => {
					r(res);
				},
				fail: err => {
					j(err);
				}
			});
		});
	}
	/**
	 * getSystemInfo -获取系统信息
	 * @return Promise(UniApp.GetSystemInfoResult)
	 */
	export function getSystemInfo(): UniApp.GetSystemInfoResult {
		return uni.getSystemInfoSync();
	}
	/**
	 * navTo -路由跳转
	 * @return Promise(void)
	 */
	export function navTo(p: string): Promise<void>;
	export function navTo(p: UniApp.NavigateToOptions): Promise<void>;
	export function navTo(p: string | UniApp.NavigateToOptions): Promise<void> {
		return new Promise((r, j) => {
			const url = typeof p === 'string' ? p : p.url;
			loading();
			uni.navigateTo({
				url : url.startsWith('/') ? url : `/${url}`,
				events: typeof p === 'string' ? {} : p.events,
				success: () => {
					r();
				},
				fail: err => {
					j(err);
				},
				complete() {
					loading(false);
				}
			});
		});
	}
	/**
	 * redirectTo -关闭当前页面，跳转到某个页面
	 * @return Promise(void)
	 */
	export function redirectTo(url: string): Promise<void> {
		return new Promise((r, j) => {
			loading();
			uni.redirectTo({
				url : url.startsWith('/') ? url : `/${url}`,
				success() {
					r();
				},
				fail(err) {
					j(err);
				},
				complete() {
					loading(false);
				}
			});
		});
	}
	/**
	 * reLaunch -关闭所有页面，打开到应用内的某个页面。
	 * @return Promise(void)
	 */
	export function reLaunch(url: string): Promise<void> {
		return new Promise((r, j) => {
			loading();
			uni.reLaunch({
				url : url.startsWith('/') ? url : `/${url}`,
				success() {
					r();
				},
				fail(err) {
					j(err);
				},
				complete() {
					loading(false);
				}
			});
		});
	}
	/**
	 * switchTab -跳转到 tabBar 页面，并关闭其他所有非 tabBar 页面
	 * @return Promise(void)
	 */
	export function switchTab(url: string): Promise<void> {
		return new Promise((r, j) => {
			uni.switchTab({
				url : url.startsWith('/') ? url : `/${url}`,
				success() {
					r();
				},
				fail(err) {
					j(err);
				}
			});
		});
	}
	/**
	 * navBack -关闭当前页面，返回上一页面或多级页面
	 * @return Promise(void)
	 */
	export function navBack(delta = 1): Promise<void> {
		return new Promise((r, j) => {
			uni.navigateBack({
				delta,
				success() {
					r();
				},
				fail(err) {
					j(err);
				}
			});
		});
	}
	/**
	 * chooseMedia -拍摄或从手机相册中选择图片或视频。
	 * @param {Object} UniApp.ChooseMediaOption
	 * @param {Boolean} rejectWithCancel 用户取消时是否返回reject
	 * @return Promise(UniApp.ChooseMediaSuccessCallbackResult)
	 */
	export function chooseMedia(p: UniApp.ChooseMediaOption, rejectWithCancel = true): Promise<UniApp.ChooseMediaSuccessCallbackResult> {
		return new Promise((r, j) => {
			uni.chooseMedia({
				...p,
				success(res) {
					r(res);
				},
				fail(err) {
					rejectWithCancel && j(err);
				}
			});
		});
	}
	/**
	 * getAccountInfo -获取当前帐号信息，可以返回小程序的Appid。如果使用了微信小程序的云端插件，还可以返回当前插件Appid、版本号
	 * @return UniApp.AccountInfo
	 */
	export function getAccountInfo(): UniApp.AccountInfo {
		return uni.getAccountInfoSync();
	}
	/**
	 * navToMini -打开另一个小程序。
	 * @return Promise(void)
	 */
	export function navToMini(p: UniApp.NavigateToMiniProgramOptions): Promise<void> {
		return new Promise((r, j) => {
			uni.navigateToMiniProgram({
				...p,
				envVersion: PD.PdHelp.getMiniEnvVersion(),
				success() {
					r();
				},
				fail(err) {
					j(err);
				}
			});
		});
	}
	/**
	 * getInsByRoute - 根据页面地址，获取该页面的实例
	 * @params {route : 页面路由地址}
	 * @returns {Page.PageInstance | undefined}
	 */
	export function getInsByRoute(route: APP_ROUTES): Page.PageInstance | undefined {
		return getCurrentPages().find(v => `/${v.route}` === route);
	}

	/**
	 * getInsByDelta - 根据delta获取页面实例
	 * @params {delta : number} 0 获取最后一页，一般都是当前页， -1 获取上一页，以此类推
	 * @returns {Page.PageInstance | undefined}
	 */
	export function getInsByDelta(delta = 0): Page.PageInstance | undefined {
		const pages = getCurrentPages();
		return pages[pages.length - 1 + delta];
	}

	/**
	 * 获取当前页面实例
	 * @param {Page.PageInstance | undefined} ins 页面实例
	 */
	export function getCurrentPageIns ():Page.PageInstance | undefined {
		return getInsByDelta(0);
	};

	/**
	 * makePhoneCall - 拨打电话
	 * @params {phonenumber : string} 电话号码
	 */
	export function makePhoneCall(phoneNumber: string): Promise<void> {
		return new Promise((r, j) => {
			if (typeof phoneNumber !== 'string') {
				j();
				throw new Error('uni-help.ts -> makePhoneCall 参数类型错误，需要string类型');
			}
			if (!phoneNumber) {
				j();
				throw new Error('uni-help.ts -> makePhoneCall 缺乏必要参数');
			};
			
			uni.makePhoneCall({
				phoneNumber,
				complete() {
					r();
				}
			});
		});
	}

	/**
	 * 下载文件
	 * @param {string} url -要下载的资源的路径
	 * @return {Promise<tempFilePath>}
	 */
	export function downloadFile(url: string): Promise<string> {
		return new Promise((r, j) => {
			uni.downloadFile({
				url,
				success: res => {
					if (res.statusCode === 200) {
						r(res.tempFilePath);
						return;
					};
					j();
				},
				fail: err => {
					j(err);
				}
			});
		});
	}

	/**
	 * canvas转图片
	 * @param {string} canvasId 画布id
	 * @param {ComponentInternalInstance} vue实例的proxy
	 * @returns {Promise<tempFilePath>} tempFilePath 生成的图片路径
	 */
	export function canvas2tempFilePath(canvasId: string, Instance?: ComponentPublicInstance): Promise<string> {
		return new Promise((r, j) => {
			uni.canvasToTempFilePath({
				canvasId,
				success: res => {
					r(res.tempFilePath);
				},
				fail: err => {
					j(err);
				}
			}, Instance);
		});
	}

	/**
	 * 保存图片到相册
	 * @param {string} filePath 要保存的文件路径
	 */
	export function saveImage2photosAlbum(filePath: string): Promise<void> {
		return new Promise((r, j) => {
			uni.saveImageToPhotosAlbum({
				filePath,
				success: () => {
					r();
				},
				fail: err => {
					if (err.errMsg === WX_AUTH_DENY_ERROR.saveImageToPhotosAlbum) {
						modal({
							title: '保存失败',
							content: "失败原因：未授权小程序【添加到相册】权限，请打开右上角胶囊按钮，授权后重新保存",
							showCancel: true,
							confirmText: '去设置'
						}).then(() => {
							uni.openSetting();
						});
						try {
							loading(false);
						} catch (error) {};
						return;
					};
					j(err);
				}
			});
		});
	}

	
	/**
	 * 更新小程序
	 */
	export function updateMiniApp() {
		if (!uni.canIUse('getUpdateManager')) return;
		const updateManager = uni.getUpdateManager();
		updateManager.onCheckForUpdate(res => {
			if (res.hasUpdate) {
				updateManager.onUpdateReady(() => {
					modal({
						title: '更新提示',
						content: '新版本已准备好，请重启应用',
						showCancel: false,
						confirmText: '立即重启'
					}).then(() => {
						updateManager.applyUpdate();
					});
				});
			};

			//监听更新失败
			updateManager.onUpdateFailed(() => {
				modal({
					title: '更新失败提示',
					content: '新版本下载失败，请删除当前小程序，重新搜索进入，以体验最新版本。',
				});
			});

		});
	}

	/**
	 * 设置tabbar标题
	 * @param {string} title 标题内容
	 */
	export function setNavBarTitle(title: string) {
		uni.setNavigationBarTitle({
			title
		});
	}

	/**
	 * 获取微信版本，基础库版本等信息
	 */
	export function getMiniAppBaseInfo() {
		return uni.getAppBaseInfo();
	}

	/**
	 * 申请授权
	 * @param {WxHelp.Permission} type 授权类型 
	 * @return {Promise<void>}
	 */
	export function authorize(type: WxUserPermission): Promise<boolean> {
		return new Promise((r) => {
			uni.authorize({
				scope: type,
				success: () => {
					r(true);
				},
				fail: err => {
					console.error('WxPermission->authorize Error：' + JSON.stringify(err));
					r(false);
				}
			});
		});
	}

	/**
	 * showActionSheet
	 */
	export function showActionSheet (itemList : string[]) : Promise<{index : number}> {
		return new Promise((r, j) => {
			uni.showActionSheet({
				itemList,
				success : res => {
					r({index : res.tapIndex});
				},
				fail : () => {
					j();
				}
			});
		});
	}

	/**
	 * 支付
	 */
	export function requestPayment (params : UniApp.RequestPaymentOptions) : Promise<void> {
		return new Promise((r,j) => {
			uni.requestPayment({
				...params,
				success : () => {
					r();
				},
				fail : err => {
					j(err);
				}
			});
		});
	}
}

